#define   NONAMELESSUNION

#include <windows.h>
#include <iostream.h>
#include <map.h>

	HINSTANCE g_hInstance = NULL;
	long g_lObjs;
	long g_lLocks;

	const wchar_t* g_SectionName = L"ActiveX";
	const wchar_t* g_idCLSID = L"CLSID";
	const wchar_t* g_idPROGID = L"PROGID";
	const wchar_t* g_idDESC = L"DESC";
	const wchar_t* g_idDLLPATH = L"DLLPATH";
	const wchar_t* g_idINIPATH = L"INIPATH";
	const wchar_t* g_idTREEDIR = L"TREEDIR";	
	const wchar_t* g_enKeys[] = {g_idCLSID, g_idPROGID, g_idDESC, g_idTREEDIR, NULL};

	map<const wchar_t*, wstring> g_params;	

#include "Functions\gEscape.hpp"	
#include "Functions\gAddRegHeader.hpp"
#include "Functions\gErrorMsg.hpp"	
#include "Functions\gFileExists.hpp"
#include "Functions\gAccessMessage.hpp"
#include "Functions\gLoadConfiguration.hpp"	
#include "Functions\gisWow64.hpp"
#include "Functions\gCheckLocationRegSvr32.hpp"
#include "Functions\gRegisterFunction.hpp"
#include "CClassFactory\CClassFactory.hpp"

BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD fdwReason, PVOID) {
	
	BOOL bResult = TRUE;	
	if (fdwReason == DLL_PROCESS_ATTACH) {
		g_hInstance = hInstance;
		bResult = gLoadConfiguration(hInstance);
		if (bResult) CoInitialize(NULL);
	}
	
	if (fdwReason == DLL_PROCESS_DETACH) {
		CoUninitialize();
	}

	return bResult;
}

STDAPI __export DllRegisterServer(void)
{
	HRESULT hr = S_OK;
	if (!gCheckLocationRegSvr32()) return E_FAIL;
	wstring bodyRegFile = gRegisterFunction(FALSE);	
	if (!bodyRegFile.empty()) {
		bodyRegFile = gAddRegHeader(bodyRegFile);
		hr = gAccessMessage(bodyRegFile);
	};
	return hr;
}

STDAPI __export DllUnregisterServer(void)
{
	HRESULT hr = S_OK;
	if (!gCheckLocationRegSvr32()) return E_FAIL;
	wstring bodyRegFile = gRegisterFunction(TRUE);	
	if (!bodyRegFile.empty()) {
		bodyRegFile = gAddRegHeader(bodyRegFile);
		hr = gAccessMessage(bodyRegFile);
	};
	return hr;
}

STDAPI __export DllGetClassObject( REFCLSID rclsid, REFIID riid, void** ppv )
{
   CClassFactory    *pCF;
   CLSID clsid = {0};
   
   HRESULT hr = CLSIDFromString(
   	const_cast<PWSTR>(g_params[g_idCLSID].c_str()), 
	&clsid
	);

   if (FAILED(hr)) {
		gErrorMsgW(
			hr, 
			const_cast<PWSTR>(g_params[g_idCLSID].c_str()),
			const_cast<PWSTR>(g_idCLSID),
			L"",
			const_cast<PWSTR>(g_params[g_idINIPATH].c_str()), 
			NULL
		);
	   	   	
	   return E_FAIL;
   };

   // Make sure the CLSID is for our Expression component
   if ( rclsid != clsid)      return( E_FAIL );
   pCF = new CClassFactory();
   if ( pCF == 0 )  return( E_OUTOFMEMORY );
   hr = pCF->QueryInterface( riid, ppv );

   // Check for failure of QueryInterface
   if ( FAILED( hr ) )
   {
      delete pCF;
   };
   
   return hr;
}

STDAPI __export DllCanUnloadNow(void)
{
    if ( g_lObjs || g_lLocks ) return( S_FALSE );
	return( S_OK );
}

extern "C" void* __declspec(dllexport) __stdcall GetRootNode() {

	CDir* pDir = new CDir(g_params[g_idTREEDIR]);   
	if (pDir == NULL) {
		gErrorMsgA(GetLastError(), "E_OUTOFMEMORY");
		return( NULL );
	};
	
	void* pvObj = NULL;
	if (FAILED(pDir->QueryInterface(IID_IDispatch, &pvObj))) {
		gErrorMsgA(GetLastError(), "IID_IDispatch");
		delete pDir;
	};
	
	return pvObj;
}
